package com.seven.smartsnmp.discover.service;

import com.seven.smartsnmp.base.SNMPSysConfig;
import com.seven.smartsnmp.discover.DeviceInfo;
import com.seven.smartsnmp.snmp.SNMPTarget;

import java.sql.Timestamp;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 设备发现接口
 */
public class SearchNodeService {

    private ConcurrentLinkedQueue<DeviceInfo> rstQueue = new ConcurrentLinkedQueue();

    public SearchNodeService() {
    }


    /**
     *
     * @param ip
     * @param snmpTargets
     * @param isUsePing
     * @return
     */
    public ConcurrentLinkedQueue<DeviceInfo> searchDevice(String ip, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        ConcurrentLinkedQueue ipQueue = new ConcurrentLinkedQueue();
        ipQueue.add(ip);
        return this.searchDeviceByNetList(ipQueue, snmpTargets, isUsePing);
    }

    public ConcurrentLinkedQueue<DeviceInfo> searchDeviceByNetList(ConcurrentLinkedQueue<String> ipQueue, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        ConcurrentLinkedQueue ipQueues = new ConcurrentLinkedQueue();
        Iterator iterator = ipQueue.iterator();
        while (iterator.hasNext()) {
            String ip = (String) iterator.next();
            int last = ip.lastIndexOf(".");
            if (last >= 0) {
                String segment = ip.substring(0, last+1);
                String beginIp = segment + "1";
                String endIP = segment + "254";
                StartEndIP startEndIP = new StartEndIP();
                startEndIP.startIP = beginIp;
                startEndIP.endIP = endIP;
                ipQueues.add(startEndIP);
            }
        }

        return this.searchDevice(ipQueues, snmpTargets, isUsePing);
    }

    public ConcurrentLinkedQueue<DeviceInfo> searchDevice(String startIp, String endIp, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        ConcurrentLinkedQueue<StartEndIP> startEndIPS = new ConcurrentLinkedQueue();
        StartEndIP startEndIP= new StartEndIP();
        startEndIP.startIP = startIp;
        startEndIP.endIP = endIp;
        startEndIPS.add(startEndIP);
        return this.searchDevice(startEndIPS, snmpTargets, isUsePing);
    }

    public ConcurrentLinkedQueue<DeviceInfo> searchDevice(ConcurrentLinkedQueue<StartEndIP> startEndIPS, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        ConcurrentLinkedQueue ipQueus = new ConcurrentLinkedQueue();
        Iterator startEndIPIterator = startEndIPS.iterator();

        while (startEndIPIterator.hasNext()) {
            StartEndIP startEndIP = (StartEndIP) startEndIPIterator.next();
            String startIP = startEndIP.startIP;
            int beginCharAt = startIP.lastIndexOf(".");
            String beginStr = startIP.substring(beginCharAt + 1);
            int  beginNum = Integer.parseInt(beginStr);
            String segment = startIP.substring(0, beginCharAt + 1);
            String endIP = startEndIP.endIP;
            int endCharAt = endIP.lastIndexOf(".");
            String endStr = endIP.substring(endCharAt + 1);
            int endNum = Integer.parseInt(endStr);
            for (int i = beginNum; i <= endNum; i++) {
                ipQueus.add(segment + i);
            }
        }
        return this.searchDeviceByIPList(ipQueus, snmpTargets, isUsePing);
    }

    public ConcurrentLinkedQueue<DeviceInfo> searchDeviceByIPList(ConcurrentLinkedQueue<String> ipQueue, List<SNMPTarget> targetList, boolean isUsePing) {
        int size = ipQueue.size();
        ThreadPoolExecutor executor;
        if (size == 0) {
            return this.rstQueue;
        } else {
            int poolSize = SNMPSysConfig.SNMPThreadPoolSize;
            if (size > poolSize) {
                SNMPSysConfig.SNMPThreadPoolSize = size;
                executor = new ThreadPoolExecutor(poolSize, size, 30L, TimeUnit.SECONDS, new LinkedBlockingQueue());
            }else {
                executor = new ThreadPoolExecutor(poolSize, poolSize, 30L, TimeUnit.SECONDS, new LinkedBlockingQueue());
            }
            Iterator iterator = ipQueue.iterator();
            while (iterator.hasNext()) {
                String ip = (String) iterator.next();
                executor.execute(new IpSearchTask(ip, targetList, this.rstQueue, isUsePing));
            }
            executor.shutdown();
            try {
                for (boolean flag = false; !flag; flag = executor.awaitTermination(1L, TimeUnit.SECONDS)) {
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("=============================");
            System.out.println(new Timestamp(System.currentTimeMillis()) + "设备搜索完备，发现的设备个数:" + this.rstQueue.size());
            return this.rstQueue;
        }
    }

}
